<?php

declare(strict_types=1);

namespace App\Common\Service;

class Arr
{

    /**
     * PHP二维数组（或任意维数组）转换成一维数组的方法
     * array_reduce函数法
     * array_walk_recursive函数法
     * array_map函数法
     */

    /**
     * Pick certain keys from array and filter empty values.
     * @param $arr
     * @param $keys
     * @param null $extra
     * @return array
     */
    public static function pick($arr, $keys, $extra = NULL)
    {
        if ($extra) {
            $keys[] = $extra;
        }
        return array_intersect_key(array_filter($arr), array_flip($keys));
    }

    /**
     * Exclude certain keys from array and filter empty values.
     * @param $arr
     * @param $keys
     * @return array
     */
    public static function exclude($arr, $keys)
    {
        $result = [];
        foreach ($arr as $k => $v) {
            if (!in_array($k, $keys)) {
                $result[$k] = $v;
            }
        }
        return $result;
    }

    /**
     * Whether keys exist in array.
     * @param $arr
     * @param $keys
     * @return bool
     */
    public static function exist($arr, $keys)
    {
        return count($keys) == count(Arr::pick($arr, $keys));
    }

    /**
     * Whether keys miss in array.
     * @param $arr
     * @param $keys
     * @return bool
     */
    public static function miss($arr, $keys)
    {
        return count($keys) != count(Arr::pick($arr, $keys));
    }

    /**
     * Whether keys exist in array.
     * @param $arr
     * @param $keys1
     * @param $keys2
     * @return bool
     */
    public static function in($arr, $keys1, $keys2)
    {
        $result = (count($keys1) == count(Arr::pick($arr, $keys1)));
        if (!$result && $keys2) {
            $result = (count($keys2) == count(Arr::pick($arr, $keys2)));
        }
        return $result;
    }

    public static function value($arr, $key, $default = NULL, $min = NULL)
    {
        if (isset($arr[$key])) {
            return $min ? max($min, $arr[$key]) : $arr[$key];
        } else {
            return $default ? $default : FALSE;
        }
    }

    public static function unset($arr, $keys)
    {
        foreach ($keys as $key) {
            unset($arr[$key]);
        }
        return $arr;
    }

    /**
     * multi array sort
     * @param $colume 排序字段
     * @param $arr    数组
     * @param $sort   排序规则：SORT_ASC，SORT_DESC
     * @return mixed
     */
    public static function multiSort($colume, $arr, $sort)
    {
        $colume = array_column($arr, $colume);
        array_multisort($colume, $sort, $arr);
        return $arr;
    }

    /**
     * 对二维数组按某个字段重新排序
     * @param array $array  参与排序的数组
     * @param string $keys  排序字段
     * @param string $sort  排序方式：asc,desc
     * @return array
     */
    public function arraySort(array $array, string $keys, string $sort='desc'): array
    {
        $newArr = $valArr = array();
        foreach ($array as $key=>$value) {
            $valArr[$key] = $value[$keys];
        }
        ($sort == 'asc') ?  asort($valArr) : arsort($valArr);
        reset($valArr);
        foreach($valArr as $key=>$value) {
            $newArr[$key] = $array[$key];
        }
        return $newArr;
    }

    /**
     * 二维数组中，某个键相同，另一个键的值相加
     * @param array $arr        要操作的数组
     * @param string $key       要参考的相同的键
     * @param string $addKey    要相加的键
     * @return array
     */
    public function addValByOtherVal(array $arr, string $key, string $addKey): array
    {
        $item=[];
        foreach($arr as $k=>$v){
            if(!isset($item[$v[$key]])){
                $item[$v[$key]] = $v[$addKey];
            }else{
                $item[$v[$key]] = bcadd((string)$item[$v[$key]], (string)$v[$addKey], 2);
            }
        }

        return $item;
    }

    /**
     * 二维数组中，某个键相同的值归置一起组成数组，相同的键为键
     * @param array $arr    要操作的数组
     * @param string $key   要参考的相同的键
     * @param string $focusKey  要归置的键
     * @return array
     */
    public function focusValBySameKey(array $arr, string $key, string $focusKey): array
    {
        $item = [];
        foreach($arr as $k => $v){
            if(!isset($item[$v[$key]])){
                $item[$v[$key]] = [$v[$focusKey]];
            }else{
                array_push($item[$v[$key]],$v[$focusKey]);
            }
        }

        return $item;
    }

    /**
     * @param $arr
     * @param $key
     * @return array
     * @author zhangzhiyuan
     */
    public function exceptArr($arr,$key): array
    {
        return array_merge(array_diff($arr, array($key)));
    }

    /**
     * 一维数组剔除特定的键
     * @param $arr
     * @param $needExceptKey
     * @return mixed
     * @author zhangzhiyuan
     */
    public function exceptArrKey(array $arr,array $needExceptKey): array
    {
        foreach($arr as $key=>$val){
            if(in_array($key,$needExceptKey)){
                unset($arr[$key]);
            }
        }
        return $arr;
    }

    /**
     * 二维数组剔除特定的键
     * @param $arr
     * @param $needExceptKey
     * @return mixed
     * @author zhangzhiyuan
     */
    public function exceptMoreArrKey(array $arr,array $needExceptKey): array
    {
        $data =[];
        foreach($arr as $val){
            foreach($val as $key=>$value){
                if(in_array($key,$needExceptKey)){
                    unset($val[$key]);
                }
            }
            $data[]=$val;
        }
        return $data;
    }
    /**
     * @param $value
     * @return bool
     * @author zhangzhiyuan
     */
    public function checkEmpty($value): bool
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;
        return false;
    }

}